const Book = require("../models/Book");
const { Op, json } = require("sequelize");
const {
  filterProperty,
  pickerProperty,
  deepClone,
} = require("../utils/operateProperty");
const validate = require("validate.js");
const rule = {
  name: {
    presence: { allowEmpty: false },
    type: "string",
  },
  imgUrl: {
    presence: { allowEmpty: false },
    type: "string",
    url: true,
  },
  publishDate: {
    presence: { allowEmpty: false },
    datetime: {
      dateOnly: true,
    },
  },
  author: {
    presence: { allowEmpty: false },
    type: "string",
  },
};
class BookService {
  /* constructor() {
    this.init();
  }
  init() {
    Book.findAll().then((books) => {
      if (books.length === 0) {
        this.addBook({
          name: "西游记",
          imgUrl: "",
          publishDate: "1592-01-01",
          author: "吴承恩",
        });
      }
    });
  } */
  addBook(bookObj) {
    bookObj = pickerProperty(bookObj, Object.keys(rule));
    return this.validateBookObj(bookObj, async (val) => {
      const book = await this.getBookByName(val);
      // console.log(book);
      if (book) {
        return Promise.reject(["This book is exist"]);
      }
    })
      .then(() => {
        // 判断数据库中是否有管理员，如果没有，自动添加一个默认管理员
        return Book.create(bookObj);
      })
      .then(() => {
        console.log("添加图书成功");
      });
  }
  deleteBook(bookId) {
    // 验证id
    const res = validate.single(studentId, {
      presence: true,
      type: "integer",
    });
    if (res)
      return Promise.reject(["id can't be blank and must be of type integer"]);
    Book.destroy({
      where: {
        id: bookId,
      },
    }).then(() => {
      console.log("删除成功");
    });
  }
  updateBook(id, bookObj) {
    // 验证id
    const res = validate.single(id, {
      presence: true,
      type: "integer",
    });
    if (res)
      return Promise.reject(["id can't be blank and must be of type integer"]);
    bookObj = pickerProperty(bookObj, Object.keys(rule));
    return this.validateBookObj(bookObj, async (val) => {
      const book = await this.getBookByName(val);
      console.log(book);
      if (!book) {
        return Promise.reject(["This book is not exist"]);
      }
    })
      .then(() => {
        return Book.update(bookObj, {
          where: {
            id: id,
          },
        });
      })
      .then(() => {
        console.log("更新成功");
      });
  }

  // 书籍查询
  // 分页查询所有书籍
  async getBooks(page = 1, limit = 10) {
    const { count, rows } = await Book.findAndCountAll({
      offset: (page - 1) * limit,
      limit: limit,
    });
    return {
      total: count,
      datas: JSON.parse(JSON.stringify(rows)).map((s) =>
        filterProperty(s, ["createdAt", "updatedAt", "deletedAt"])
      ),
    };
  }
  // 按书名查询
  async getBookByName(name) {
    const res = await validate.single(name, rule.name);
    if (res) return Promise.reject(res);
    const books = await Book.findOne({
      where: {
        name: name,
      },
    });
    return filterProperty(JSON.parse(JSON.stringify(books)), [
      "createdAt",
      "updatedAt",
      "deletedAt",
    ]);
  }
  // 按书名模糊查询
  async getBookByNameLike(name, page = 1, limit = 10) {
    const { count, rows } = await Book.findAndCountAll({
      where: {
        name: {
          [Op.like]: `%${name}%`,
        },
      },
      offset: (page - 1) * limit,
      limit: limit,
    });
    return {
      total: count,
      data: JSON.parse(JSON.stringify(rows)).map((s) =>
        filterProperty(s, ["createdAt", "updatedAt", "deletedAt"])
      ),
    };
  }

  // 按作者查询
  async getBookByAuthorNameLike(author, page = 1, limit = 10) {
    const { count, rows } = await Book.findAndCountAll({
      where: {
        author: {
          [Op.like]: `%${author}%`,
        },
      },
      offset: (page - 1) * limit,
      limit: limit,
    });
    return {
      total: count,
      data: JSON.parse(JSON.stringify(rows)).map((s) =>
        filterProperty(s, ["createdAt", "updatedAt", "deletedAt"])
      ),
    };
  }

  validateBookObj(bookObj, validator) {
    const rules = deepClone(rule);
    rules.name.exist = {
      validator,
    };
    // console.log("rules", rules);
    return validate.async(bookObj, rules);
  }
}

const bookService = new BookService();
module.exports = bookService;
